package com.plian.system.service.pm.property;


import com.plian.Tools.CollectionUtil;
import com.plian.Tools.StringUtil;
import com.plian.Tools.Tree;
import com.plian.system.vo.pm.property.TreeSumVO;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;

/**
 * @description:
 * @author: gangan
 * @create: 2020-09-14 10:04
 */
public class PropertyTreeExportHelper {

    private static final Logger log = LoggerFactory.getLogger(PropertyTreeExportHelper.class);
    /**
     * id tree
     */
    private static HashMap<String, Tree> nodeMap = new HashMap<String,Tree>();
    /**
     * 层次 对应节点数量
     */
    private static HashMap<Integer, Integer> levelSizeMap = new HashMap<>();
    /**
     * 层次 对应节点
     */
    private static HashMap<Integer, List<Tree>> levelTreeMap = new HashMap<>();
    /**
     * id parentId
     */
    private static HashMap<String, String> parentIdMap = new HashMap<>();

    /**
     * 数据处理
     * @param nodes
     * @param parentId
     */
    public static void data(List<Tree> nodes, String parentId){
        if (CollectionUtil.isNotEmpty(nodes)){
            for (Tree tree : nodes){
                nodeMap.put(tree.getId(), tree);
                int level = tree.getLevel();
                int size = 0;
                List<Tree> levelTrees = new ArrayList<>();
                if (levelSizeMap.containsKey(level)){
                    size = levelSizeMap.get(level);
                    levelTrees = levelTreeMap.get(level);
                }
                levelTrees.add(tree);
                levelSizeMap.put(level, size +1);
                levelTreeMap.put(level, levelTrees);
                if (StringUtil.isNotBlank(parentId)){
                    parentIdMap.put(tree.getId(), parentId);
                }
                if (CollectionUtil.isNotEmpty(tree.getChildren())){
                    data(tree.getChildren(), tree.getId());
                }

            }
        }
    }

    /**
     * 生成excel
     * @param nodes
     * @param treeSumVOS
     * @param path
     * @param fileName
     * @throws IOException
     */
    public static void create(List<Tree> nodes, List<TreeSumVO> treeSumVOS, String path, String fileName) throws IOException {
        nodeMap.clear();
        levelSizeMap.clear();
        levelTreeMap.clear();
        parentIdMap.clear();
        data(nodes, null);

        XSSFWorkbook work = new XSSFWorkbook();
        Sheet sheet = work.createSheet("产权树");

        List<Integer> levelList = new ArrayList<>();
        Iterator its = levelSizeMap.keySet().iterator();
        while(its.hasNext()){
            levelList.add((Integer) its.next());

        }
        Collections.sort(levelList);
        int rowCount = (levelList.size() * 2) - 1;

        //总列数
        int cellCount = 0;

        for (Integer level : levelList){
            cellCount = cellCount + levelTreeMap.get(level).size();
        }

        cellCount = (cellCount * 2) - 1;

        //创建每行每列；
        for(int i = 0; i < rowCount; i++){
            Row row = sheet.createRow(i);
            row.setHeightInPoints(100);
            for(int j = 0; j < cellCount * 2; j++){
                row.createCell(j);
            }
        }


        for(int i = 0; i < cellCount; i++){
            sheet.setColumnWidth(i, 40 * 256);
        }
        Map<String, Integer> startIndexMap = new HashMap<>();
        Map<String, Integer> indexMap = new HashMap<>();
        for (Integer level : levelList){
            List<Tree> trees = levelTreeMap.get(level);

            if (level == 1){
                Row row = sheet.getRow(0);
                row.getCell(cellCount/2).setCellValue(trees.get(0).getName());
                if (levelList.size() > 1){
                    createLine(work, sheet, cellCount/2,cellCount/2,1, 1, 1);
                }

                if (trees.get(0).getColor() != null && trees.get(0).getColor() != 0){
                    setColor(work, row.getCell(cellCount/2), trees.get(0).getColor());
                }else {
                    setFont(work, row.getCell(cellCount/2));
                }
            }else {
                Row row = sheet.getRow(level * 2 - 2);
                int startIndex = 1;
                int endIndex = 1;

                int minChildIndex = 1;
                int maxChildIndex = 1;
                for (int i = 0; i < trees.size(); i++){
                    Tree tree = trees.get(i);

                    int childrenSize = 1;

                    List<Tree> children = tree.getChildren();
                    if (CollectionUtil.isNotEmpty(children)){
                        childLevelSizeMap.clear();
                        childLevelList.clear();
                        childrenSize = getMixChildSize(children);
                    }

                    if (level == 2) {
                        // 第二层 特殊处理
                        if (i > 0){
                            startIndex = endIndex + 2;
                        }
                        endIndex = startIndex + ((childrenSize-1) * 2);
                        if (endIndex < startIndex){
                            endIndex = startIndex;
                        }
                    }else {
                        // 第三层 开始 从 startIndexMap中取开始的坐标
                        startIndex = startIndexMap.get(parentIdMap.get(tree.getId()));
                        endIndex = startIndex + ((childrenSize-1) * 2);
                        if (endIndex < startIndex){
                            endIndex = startIndex;
                        }

                        startIndexMap.put(parentIdMap.get(tree.getId()), endIndex + 2);
                    }
                  try {

                      //存开始坐标
                      startIndexMap.put(tree.getId(), startIndex);

                      //填充数据的坐标
                      int childIndex = (startIndex + endIndex) / 2 - 1;
                      if (childrenSize > 3 && childrenSize % 2 == 1){
                          childIndex = childIndex + 1;
                      }

                      if (tree.getColor() != null && tree.getColor() != 0){
                          setColor(work, row.getCell(childIndex), tree.getColor());
                      }else {
                          setFont(work, row.getCell(childIndex));
                      }
                      //
                      indexMap.put(tree.getId(), childIndex);

                      //第二层 横线用
                      if (i==0 || minChildIndex > childIndex){
                          minChildIndex = childIndex;
                      }

                      if (maxChildIndex < childIndex){
                          maxChildIndex = childIndex;
                      }
                      row.getCell(childIndex).setCellValue(tree.getName());
                      createLine(work, sheet, childIndex, childIndex,level * 2 - 3, level * 2 - 2, 2);
                      if (CollectionUtil.isNotEmpty(children)){
                          createLine(work, sheet, childIndex, childIndex,level * 2 - 1, level * 2 - 1, 1);
                      }
                  }catch (Exception e){
                      log.error(e + "");
                      log.error(startIndex + "-" + endIndex);
                  }

                }

                if (level == 2 && trees.size() > 1){
                    //第二层的横线
                    createLine(work, sheet, minChildIndex, maxChildIndex,1, 1, 3);
                }
            }

        }

        //给第三层开始画横线
        for (int i = 1; i < levelList.size(); i++){
            int level = levelList.get(i);
            List<Tree> trees = levelTreeMap.get(level);
            for (Tree tree : trees){
                List<Tree> children = tree.getChildren();
                if (CollectionUtil.isNotEmpty(children) && children.size() > 1){
                    createLine(work, sheet, indexMap.get(children.get(0).getId()),
                            indexMap.get(children.get(children.size() - 1).getId()),level * 2 - 1, level * 2 - 1, 3);
                }
            }

        }

        int addRow = 3;
        if (CollectionUtil.isNotEmpty(treeSumVOS)){
            addRow = addRow + treeSumVOS.size();
        }

        //统计模块创建每行每列；
        for(int i = rowCount; i < rowCount + addRow; i++){
            Row row = sheet.createRow(i);
            row.setHeightInPoints(60);
            for(int j = 0; j < 5; j++){
                row.createCell(j);
            }
        }

        for (int i = 1 ; i< addRow; i++){
            Row row = sheet.getRow(rowCount + i);
            if (i == 1){
                setBorderAndFont(work, row.getCell(0));
                setBorderAndColor(work, row.getCell(1), IndexedColors.CORAL.getIndex());
                setBorderAndColor(work, row.getCell(2), IndexedColors.LIGHT_GREEN.getIndex());
                setBorderAndColor(work, row.getCell(3), IndexedColors.TAN.getIndex());
                setBorderAndFont(work, row.getCell(4));
            }

            if (i == 2){
                row.getCell(1).setCellValue("全资");
                row.getCell(2).setCellValue("控股");
                row.getCell(3).setCellValue("参股");
                row.getCell(4).setCellValue("公司数");
                setBorderAndFont(work, row.getCell(0));
                setBorderAndFont(work, row.getCell(1));
                setBorderAndFont(work, row.getCell(2));
                setBorderAndFont(work, row.getCell(3));
                setBorderAndFont(work, row.getCell(4));
            }

            if (i > 2){
                TreeSumVO treeSumVO = treeSumVOS.get(i - 3);
                    row.getCell(0).setCellValue(treeSumVO.getCountName());
                    row.getCell(1).setCellValue(treeSumVO.getWhollyCount());
                    row.getCell(2).setCellValue(treeSumVO.getHoldingCount());
                    row.getCell(3).setCellValue(treeSumVO.getParticipationCount());
                    row.getCell(4).setCellValue(treeSumVO.getCompanyCount());
                    setBorderAndFont(work, row.getCell(0));
                    setBorderAndFont(work, row.getCell(1));
                    setBorderAndFont(work, row.getCell(2));
                    setBorderAndFont(work, row.getCell(3));
                    setBorderAndFont(work, row.getCell(4));
            }
        }


        File file = new File(path + fileName);
        FileOutputStream fileOut = new FileOutputStream(file);
        work.write(fileOut);

        work.close();
        fileOut.close();
    }

    /**
     * 获取子表最大的size
     * @param children
     * @param size
     * @return
     */
    private static HashMap<Integer, Integer> childLevelSizeMap = new HashMap<>();
    private static List<Integer> childLevelList = new ArrayList<>();
    private static List<Tree> childNodes = new ArrayList<>();

    public static int getMaxLevel(List<Tree> children){
        for(Tree child : children){
            childLevelList.add(child.getLevel());

            if (CollectionUtil.isNotEmpty(child.getChildren())){
                getMaxLevel(child.getChildren());
            }
        }
        int maxLevel = 3;
        if (CollectionUtil.isNotEmpty(childLevelList)){
            for (Integer level : childLevelList){
                if (level > maxLevel){
                    maxLevel = level;
                }
            }
        }
        return maxLevel;
    }

    public static String getMaxChildLevel(List<Tree> children){
        for(Tree child : children){
            int level = child.getLevel();
            int childSize = 0;
            if (childLevelSizeMap.containsKey(level)){
                childSize = childLevelSizeMap.get(level);
            }
            childLevelSizeMap.put(level, childSize +1);
            childNodes.add(child);
            if (CollectionUtil.isNotEmpty(child.getChildren())){
                getMaxChildLevel(child.getChildren());
            }
        }
        int maxSize = 1;
        String max = "0-0";
        if (CollectionUtil.isNotEmpty(childLevelSizeMap)){
            for(Map.Entry<Integer, Integer> entry : childLevelSizeMap.entrySet()){
                Integer mapKey = entry.getKey();
                Integer mapValue = entry.getValue();
                if (maxSize <= mapValue){
                    max = mapKey + "-" + mapValue;
                }
            }
        }
        return max;
    }

    public static int getMixChildSize(List<Tree> children){
        childLevelSizeMap.clear();
        childNodes.clear();
        String max =  getMaxChildLevel(children);
        String[] strings = max.split("-");
        Integer level = Integer.valueOf(strings[0]);
        Integer size = Integer.valueOf(strings[1]);
        for (Tree tree : childNodes){
            if (tree.getLevel() < level && CollectionUtil.isEmpty(tree.getChildren())){
                size = size + 1;
            }
        }

        return size;
    }

    /**
     * 画线
     * @param workbook
     * @param sheet
     * @param startCol
     * @param endCol
     * @param startRow
     * @param endRow
     * @param type
     */
    public static void createLine(XSSFWorkbook workbook, Sheet sheet, int startCol, int endCol, int startRow, int endRow, int type){
        CreationHelper helper = workbook.getCreationHelper();
        Drawing drawing = sheet.createDrawingPatriarch();
        ClientAnchor anchor = helper.createClientAnchor();
        anchor.setCol1(startCol);
        anchor.setCol2(endCol);
        anchor.setRow1(startRow);
        anchor.setRow2(endRow);
        switch (type){
            case 1:
                //parent节点线
                anchor.setDx1(1333500);
                anchor.setDy1(0);
                anchor.setDx2(1333500);
                anchor.setDy2(633412);
                break;
            case 2:
                //子节点线
                anchor.setDx1(1333500);
                anchor.setDy1(633413);
                anchor.setDx2(1333500);
                anchor.setDy2(0);
                break;
            case 3:
                //横线
                anchor.setDx1(1333500);
                anchor.setDy1(633412);
                anchor.setDx2(1333500);
                anchor.setDy2(633413);
                break;
        }

        XSSFSimpleShape shape = ((XSSFDrawing)drawing).createSimpleShape((XSSFClientAnchor)anchor);
        shape.setShapeType(ShapeTypes.LINE);
        shape.setLineWidth(1.5);
        shape.setLineStyle(0);
        shape.setLineStyleColor(128,128,128);
    }

    /**
     * 设置颜色 字体样式 等
     * @param workbook
     * @param cell
     * @param color
     */
    public static void setColor(XSSFWorkbook workbook, Cell cell, short color){
        XSSFCellStyle style = workbook.createCellStyle();
        style.setFillForegroundColor(color);
        style.setWrapText(true);
        //左右居中
        style.setAlignment(HorizontalAlignment.CENTER);
        //上下居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setAlignment(HorizontalAlignment.CENTER);
        cell.setCellStyle(style);
    }

    public static void setFont(XSSFWorkbook workbook, Cell cell){
        XSSFCellStyle style = workbook.createCellStyle();
        style.setWrapText(true);
        //左右居中
        style.setAlignment(HorizontalAlignment.CENTER);
        //上下居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setAlignment(HorizontalAlignment.CENTER);
        cell.setCellStyle(style);
    }

    public static void setBorderAndColor(XSSFWorkbook workbook, Cell cell, short color){
        XSSFCellStyle style = workbook.createCellStyle();
        style.setFillForegroundColor(color);
        style.setWrapText(true);
        //左右居中
        style.setAlignment(HorizontalAlignment.CENTER);
        //上下居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setAlignment(HorizontalAlignment.CENTER);

        //下边框
        style.setBorderBottom(BorderStyle.THIN);
        //左边框
        style.setBorderLeft(BorderStyle.THIN);
        //上边框
        style.setBorderTop(BorderStyle.THIN);
        //右边框
        style.setBorderRight(BorderStyle.THIN);
        cell.setCellStyle(style);
    }

    public static void setBorderAndFont(XSSFWorkbook workbook, Cell cell){
        XSSFCellStyle style = workbook.createCellStyle();
        style.setWrapText(true);
        //左右居中
        style.setAlignment(HorizontalAlignment.CENTER);
        //上下居中
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setAlignment(HorizontalAlignment.CENTER);
        //下边框
        style.setBorderBottom(BorderStyle.THIN);
        //左边框
        style.setBorderLeft(BorderStyle.THIN);
        //上边框
        style.setBorderTop(BorderStyle.THIN);
        //右边框
        style.setBorderRight(BorderStyle.THIN);
        cell.setCellStyle(style);

    }

}
